package com.andy.wang.controller;

import com.alibaba.fastjson.JSON;
import com.andy.wang.pojo.*;
import com.andy.wang.service.AccroomService;
import com.andy.wang.service.RoomService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Component
@Slf4j
@ServerEndpoint("/webSocketRoomUser/{rid}/{username}/{userID}") //暴露的ws应用的路径
public class WebSocketRoomUser implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        WebSocketRoomUser.applicationContext = applicationContext;
    }

    /**
     * 获取 applicationContext
     *
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    /**
     * 当前在线客户端数量（线程安全的）
     */
    private static AtomicInteger onlineClientNumber = new AtomicInteger(0);

    /**
     * 当前在线客户端集合（线程安全的）：以键值对方式存储，key是连接的编号，value是连接的对象
     */
    private static Map<String, Session> onlineClientMap = new ConcurrentHashMap<>();

    /**
     * 当前用户进入的房间号
     */
    public static int rid=0;

    /**
     * 当前用户进入的房间号的其他用户ID
     */
    private static ArrayList<String> userIds = null;

    /**
     * 客户端与服务端连接成功
     *
     * @param session
     * @param username
     */
    @OnOpen
    public static void onOpen(Session session, @PathParam("rid")int rid2,@PathParam("username") String username, @PathParam("userID") String userID) {
        /*
            do something for onOpen
            与当前客户端连接成功时
         */
        rid = rid2;
        onlineClientNumber.incrementAndGet();//在线数+1
        onlineClientMap.put(userID, session);//添加当前连接的session
        log.info("有新用户连接");
        roomUser();
    }

    /**
     * 客户端与服务端连接关闭
     *
     * @param session
     * @param username
     */
    @OnClose
    public static void onClose(Session session, @PathParam("username") String username,@PathParam("userID") String userID) {
        /*
            do something for onClose
            与当前客户端连接关闭时
         */

        onlineClientNumber.decrementAndGet();//在线数-1
        onlineClientMap.remove(userID);//移除当前连接的session
        log.info("时间[{}]：与用户[{}]的连接关闭，当前连接编号[{}]，当前连接总数[{}]",
                new Date().toLocaleString(),
                username,
                userID,
                onlineClientNumber);
    }

    /**
     * 客户端与服务端连接异常
     *
     * @param error
     * @param session
     * @param username
     */
    @OnError
    public static void onError(Throwable error, Session session, @PathParam("username") String username) {
        /*
            do something for onError
            与当前客户端连接异常时
         */
        error.printStackTrace();
    }

    //给指定客户端发送消息，通过UserID和连接编号找到Session发送       // 连接编号添加的是用户ID
    private static void roomUser() {
        LambdaQueryWrapper<Accroom> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(Accroom::getEnteredRoom)
                .eq(Accroom::getRid,rid);
        AccroomService accroomService = getApplicationContext().getBean(AccroomService.class);
        List<Accroom> userList = accroomService.list(lambdaQueryWrapper);
        userIds = new ArrayList<>();
        for (Accroom accroom : userList) {
            userIds.add(String.valueOf(accroom.getEnteredRoom()));
        }
        RoomService roomService = getApplicationContext().getBean(RoomService.class);
        List<User> roomUsers = roomService.getRoomUsers(rid);
        try {
            for (Object i : userIds) {
                Session session = onlineClientMap.get(i);
                if (session != null) {
                    session.getAsyncRemote()
                            .sendText(JSON.toJSONString(roomUsers));
                    log.info(String.valueOf(session.getAsyncRemote()));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }
}

